﻿#region Copyright information
// 
// Copyright © 2005-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the Biological Object Library and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: SokalSneath.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@gmail.com
// - Date Created: 2012-09-06 11:39 AM
// - Last Modified: 2013-01-25 3:59 PM
// 
#endregion
using System;
using System.Collections.Generic;

namespace BOL.Linq.Distances
{
    public static partial class Similarity
    {
        /// <summary>
        ///                    a
        /// SokalSneath1 = ------------
        ///                a + 2b + 2c
        /// </summary>
        public static double SokalSneath1(this IEnumerable<bool> first, IEnumerable<bool> second)
        {
            var bc = first.BinaryCardinality(second);

            return bc.Item1 / (bc.Item1 + 2.0 * bc.Item2 + 2.0 * bc.Item3);
        }

        
        /// /// <summary>
        ///                    2a + 2d
        /// SokalSneath2 = ---------------
        ///                2a + b + c + 2d
        /// </summary>
        public static double SokalSneath2(this IEnumerable<bool> first, IEnumerable<bool> second)
        {
            var bc = first.BinaryCardinality(second);

            var twoAd = 2.0 * (bc.Item1 + bc.Item4);

            return twoAd / (twoAd + bc.Item2 + bc.Item3);
        }

        /// <summary>
        ///                 a + d
        /// SokalSneath3 = -------
        ///                 b + c
        /// </summary>
        public static double SokalSneath3(this IEnumerable<bool> first, IEnumerable<bool> second)
        {
            var bc = first.BinaryCardinality(second);

            return (bc.Item1 + bc.Item4) / (double)(bc.Item2 + bc.Item3);
        }

        /// <summary>
        ///                          a       a       d       d
        /// SokalSneath4 = 0.25 * [----- + ----- + ----- + -----]
        ///                        a + b   a + c   b + d   b + d
        /// </summary>
        public static double SokalSneath4(this IEnumerable<bool> first, IEnumerable<bool> second)
        {
            var bc = first.BinaryCardinality(second);

            return 0.25 * bc.Item1 / (bc.Item1 + bc.Item2) +  
                0.25 * bc.Item1 / (bc.Item1 + bc.Item3) +
                0.25 * bc.Item4 / (bc.Item2 + bc.Item4) +
                0.25 * bc.Item4 / (bc.Item2 + bc.Item4);
        }

        /// <summary>
        ///                               ad
        /// SokalSneath5 = --------------------------------
        ///                (a + b)(a + c)(b + d)sqrt(c + d)
        /// </summary>
        public static double SokalSneath5(this IEnumerable<bool> first, IEnumerable<bool> second)
        {
            var bc = first.BinaryCardinality(second);

            return (double)bc.Item1 * bc.Item4 / (bc.Item1 + bc.Item2) / (bc.Item1 + bc.Item3) / (bc.Item2 + bc.Item4) / Math.Sqrt(bc.Item3 + bc.Item4);
        }
    }
}
